package com.geecity.flowable.flowabledemo.controller;

import lombok.extern.slf4j.Slf4j;
import org.flowable.engine.HistoryService;
import org.flowable.engine.RepositoryService;
import org.flowable.engine.RuntimeService;
import org.flowable.engine.TaskService;
import org.flowable.engine.history.HistoricProcessInstance;
import org.flowable.engine.repository.Deployment;
import org.flowable.engine.runtime.ProcessInstance;
import org.flowable.task.api.Task;
import org.flowable.task.api.history.HistoricTaskInstance;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.bind.annotation.*;

import java.util.*;

/**
 * 请假流程控制器
 * @author yuanDing
 * @date 2025-07-08
 */
@RestController
@Slf4j
@RequestMapping("/flowable")
public class FlowableController {

//    @Autowired
    private HistoryService historyService;

//    @Autowired
    private RepositoryService repositoryService;

//    @Autowired
    private RuntimeService runtimeService;

//    @Autowired
    private TaskService taskService;

    /**
     * 部署流程定义
     */
    @GetMapping("/deploy")
    public String deployProcess() {
        log.info("开始部署请假流程");
        Deployment deployment = repositoryService.createDeployment()
                .addClasspathResource("processes/leave.bpmn20.xml") // 放在 resources/processes/
                .name("请假流程")
                .deploy();
        log.info("流程部署成功，deploymentId: {}", deployment.getId());
        return "部署成功，deploymentId: " + deployment.getId();
    }

    /**
     * 启动流程实例（传入请假人名）
     */
    @PostMapping("/start")
    public String startProcess(@RequestParam String employee) {
        log.info("开始启动请假流程，请假人: {}", employee);
        Map<String, Object> vars = new HashMap<>();
        vars.put("employee", employee);
        ProcessInstance instance = runtimeService.startProcessInstanceByKey("leaveProcess", vars);
        log.info("流程启动成功，实例ID: {}", instance.getId());
        Task task = taskService.createTaskQuery().processInstanceId(instance.getId()).singleResult();
        taskService.complete(task.getId());
        return "流程启动成功，实例ID：" + instance.getId() + " 任务ID: " + task.getId();
    }

    @GetMapping("/tasks/node")
    public List<Map<String, Object>> getProcessInstancesByNode(@RequestParam String nodeId) {
        List<Task> tasks = taskService.createTaskQuery()
                .taskDefinitionKey(nodeId)
                .list();

        List<Map<String, Object>> result = new ArrayList<>();
        for (Task task : tasks) {
            Map<String, Object> info = new HashMap<>();
            info.put("taskId", task.getId());
            info.put("taskName", task.getName());
            info.put("processInstanceId", task.getProcessInstanceId());
            info.put("assignee", task.getAssignee());
            info.put("createTime", task.getCreateTime());
            // 可选：获取流程变量
            Map<String, Object> vars = runtimeService.getVariables(task.getExecutionId());
            info.put("variables", vars);
            result.add(info);
        }
        return result;
    }

    @PostMapping("/tasks/clear")
    public String clearTasksByNode(@RequestParam("nodeId") String nodeId) {
        List<Task> tasks = taskService.createTaskQuery()
                .taskDefinitionKey(nodeId)
                .list();

        int count = 0;
        for (Task task : tasks) {
//            taskService.complete(task.getId()); // 直接完成，不传任何变量
            String processInstanceId = task.getProcessInstanceId();
            runtimeService.deleteProcessInstance(processInstanceId, "强制流程结束");
            count++;
        }

        return "已强制结束节点 " + nodeId + " 上的任务共 " + count + " 个。";
    }



    /**
     * 查询当前经理审批任务
     */
    @GetMapping("/tasks/manager")
    public List<Map<String, Object>> listManagerTasks() {
        log.info("查询经理待审批任务");
        List<Task> tasks = taskService.createTaskQuery()
                .taskAssignee("manager")
                .orderByTaskCreateTime().desc()
                .list();

        List<Map<String, Object>> result = new ArrayList<>();
        for (Task task : tasks) {
            Map<String, Object> t = new HashMap<>();
            t.put("taskId", task.getId());
            t.put("taskName", task.getName());
            t.put("createTime", task.getCreateTime());
            // 获取流程实例ID
            String processInstanceId = task.getProcessInstanceId();
            // 获取流程变量
            Map<String, Object> processVariables = runtimeService.getVariables(processInstanceId);
            t.put("employee", processVariables.get("employee")); // 添加请假人信息
            t.put("processInstanceId", processInstanceId);
            result.add(t);
        }
        log.info("查询到{}条待审批任务", result.size());
        return result;
    }

    /**
     * 审批：通过或驳回
     * @param taskId 任务ID
     * @param approved true = 通过，false = 驳回
     */
    @PostMapping("/approve")
    public String approve(@RequestParam String taskId, @RequestParam Boolean approved) {
        log.info("处理审批任务ID: {}, 审批结果: {}", taskId, approved ? "通过" : "驳回");
        Map<String, Object> vars = new HashMap<>();
        vars.put("approved", approved);
        taskService.complete(taskId, vars);
        log.info("审批处理完成");
        return approved ? "审批通过" : "审批驳回";
    }


    @GetMapping("/deployment/list")
    public List<Map<String, Object>> listAllDeployments() {
        List<Deployment> deployments = repositoryService.createDeploymentQuery()
                .orderByDeploymentTime().desc()
                .list();

        List<Map<String, Object>> result = new ArrayList<>();
        for (Deployment d : deployments) {
            Map<String, Object> item = new HashMap<>();
            item.put("deploymentId", d.getId());
            item.put("name", d.getName());
            item.put("deploymentTime", d.getDeploymentTime());
            result.add(item);
        }

        return result;
    }

    @DeleteMapping("/deployment/delete-all")
    public String deleteAllDeployments() {
        List<Deployment> deployments = repositoryService.createDeploymentQuery().list();
        int count = 0;
        for (Deployment d : deployments) {
            repositoryService.deleteDeployment(d.getId(), true); // true 表示级联删除实例和历史
            count++;
        }
        return "已删除所有部署流程，共计：" + count + " 个。";
    }


    /**
     * 查询某个流程实例的历史任务列表
     * @param processInstanceId 流程实例ID
     * @return 历史任务列表
     */
    @GetMapping("/tasks/{processInstanceId}")
    public List<Map<String, Object>> getHistoricTasks(@PathVariable String processInstanceId) {
        List<HistoricTaskInstance> historicTasks = historyService
                .createHistoricTaskInstanceQuery()
                .processInstanceId(processInstanceId)
                .orderByHistoricTaskInstanceStartTime()
                .asc()
                .list();

        List<Map<String, Object>> result = new ArrayList<>();
        for (HistoricTaskInstance task : historicTasks) {
            Map<String, Object> taskInfo = new HashMap<>();
            taskInfo.put("id", task.getId());
            taskInfo.put("name", task.getName());
            taskInfo.put("startTime", task.getStartTime());
            taskInfo.put("endTime", task.getEndTime());
            taskInfo.put("assignee", task.getAssignee());
            taskInfo.put("taskDefinitionKey", task.getTaskDefinitionKey());
            
            // 获取任务的流程变量
            Map<String, Object> historicVariables = historyService.createHistoricVariableInstanceQuery()
                    .processInstanceId(processInstanceId)
                    .taskId(task.getId())
                    .list()
                    .stream()
                    .collect(HashMap::new,
                            (map, variable) -> map.put(variable.getVariableName(), variable.getValue()),
                            HashMap::putAll);
            taskInfo.put("variables", historicVariables);
            
            result.add(taskInfo);
        }
        return result;
    }


    /**
     * 查询所有历史流程实例（分页示例）
     * @param page 页码，从1开始
     * @param size 每页大小
     * @return 历史流程实例列表
     */
    @GetMapping("/process-instances")
    public List<Map<String, Object>> getAllHistoricProcessInstances(
            @RequestParam(defaultValue = "1") int page,
            @RequestParam(defaultValue = "20") int size) {

        int firstResult = (page - 1) * size;

        List<HistoricProcessInstance> historicProcessInstances = historyService
                .createHistoricProcessInstanceQuery()
                .orderByProcessInstanceStartTime()
                .desc()
                .listPage(firstResult, size);

        List<Map<String, Object>> result = new ArrayList<>();
        for (HistoricProcessInstance instance : historicProcessInstances) {
            Map<String, Object> data = new HashMap<>();
            data.put("id", instance.getId());
            data.put("startTime", instance.getStartTime());
            data.put("endTime", instance.getEndTime());
            // 获取流程定义名称
            String processDefinitionName = repositoryService.createProcessDefinitionQuery()
                    .processDefinitionId(instance.getProcessDefinitionId())
                    .singleResult()
                    .getName();
            data.put("processDefinitionName", processDefinitionName);
            result.add(data);
        }

        return result;
    }

}
